#include <iostream>
#include <math.h>
#include <limits.h>
#include "ALU_DEF.h"
#include "ALU_DSQ.h"

using namespace std;

ALU_DSQ::ALU_DSQ()
{
	Ready = true;
	inputA = 0;
	inputB = 0;
	outputZ = 0;
	OpCode = NOP_OPCODE;
	CyclesLeft = 0;
}

void ALU_DSQ::update()
{
	long long int temp = 0;
	unsigned long long int temp2= 0;
	unsigned int temp3 = 0;

	if(Ready)
	{
		if( NOP_OPCODE != OpCode )
		{
			switch (OpCode)
			{
			case IDIV_OPCODE:
				CyclesLeft = IDIV_DELAY;
				break;
			case UDIV_OPCODE:
				CyclesLeft = UDIV_DELAY;
				break;
			case IDIVR_OPCODE:
				CyclesLeft = IDIVR_DELAY;
				break;
			case UDIVR_OPCODE:
				CyclesLeft = UDIVR_DELAY;
				break;
			case FDIV_OPCODE:
				CyclesLeft = FDIV_DELAY;
				break;
			case FSQRT_OPCODE:
				CyclesLeft = FSQRT_DELAY;
				break;
			}

			Ready = false;
			update();
		}
	}
	else // Not ready, processing operation
	{
		CyclesLeft--;

		if( 0 == CyclesLeft )
		{
			switch( OpCode )
			{
				case IDIV_OPCODE:
					outputZ = inputA / inputB;
					break;
				case UDIV_OPCODE:
					outputZ = (unsigned int) inputA / (unsigned int) inputB;
					break;
				case IDIVR_OPCODE:
					outputZ = inputA % inputB;
					break;
				case UDIVR_OPCODE:
					outputZ = (unsigned int) inputA % (unsigned int) inputB;
					break;
				case FDIV_OPCODE:
					outputFZ = inputFA / inputFB;
					break;
				case FSQRT_OPCODE:
					outputFZ = sqrt(inputFA);
			}

			Ready = true;
		}
	}
}

int ALU_DSQ::getOutput()
{
	return outputZ;
}

float ALU_DSQ::getOutputF()
{
	return outputFZ;
}

bool ALU_DSQ::isReady()
{
	return Ready;
}
